package awesome.cpu.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import awesome.cpu.control.CentralProcessorUnit;
import awesome.cpu.gui.GUIOutput;

public class Assembler {

	
	public static byte[] asmToCodeBySrc(String srcCode) {
		List<Byte> codeList = new ArrayList<Byte>();
		BufferedReader br = new BufferedReader(new StringReader(srcCode));
		String line = null;
		int lineNumber = 0;
		try {
			while ((line = br.readLine()) != null) {
				if (line.matches(" *")) continue;	// pass blank line
				int ins = getCode(line);
				if (ins != 0) {
					lineNumber++;
					codeList.add((byte)ins);
					codeList.add((byte)(ins >>> 8));
					codeList.add((byte)(ins >>> 16));
					codeList.add((byte)(ins >>> 24));
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		codeList.add((byte)-1);
		codeList.add((byte)-1);
		codeList.add((byte)-1);
		codeList.add((byte)-1);
		lineNumber++;
		byte code[] = new byte[lineNumber << 2];
		for (int i = 0; i < code.length; i++) {
			code[i] = codeList.get(i);
		}
		return code;
	}
	
	private final static Pattern digitPattern = Pattern.compile("\\d+");
	private final static Pattern immPattern = Pattern.compile("(|-)\\d+");
	
	private static int getCode(String asm) {
		int code = 0;
		
		Matcher matcher;
		
		if (asm.matches("END *")){
			//END			
			code = 0xffffffff;
			//System.out.println("Assembler : End Code = " + code);
			return code;
		}
		
		if (asm.matches("(ADD|SUB|MUL|AND|OR) +r\\d+, +r\\d+, +r\\d+ *")) {
			// ADD/SUB/MUL/AND/OR rd, rs1, rs2
			
			int rd, rs1, rs2;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			
			// ADD: 08H; SUB: 04H; MUL: 00H; AND: 00H; OR: 18H
			int op = asm.startsWith("ADD") ? 0x08 :
					asm.startsWith("SUB") ? 0x04 : 
					asm.startsWith("OR") ? 0x18 : 0x00;
			// ADD: 00H; SUB: 00H; MUL: 09H; AND: 00H; OR: 00H 
			int func = asm.startsWith("MUL") ? 0x09 : 0x00;
			
			code = (op << 24) | (rs1 << 19) | (rd << 14) | (func << 5) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println((asm.startsWith("ADD") ? "ADD " :
					asm.startsWith("SUB") ? "SUB " :
					asm.startsWith("MUL") ? "MUL " :
					asm.startsWith("AND") ? "AND " : "OR ")
					+"r"+rd+", r"+rs1+", r"+rs2);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("(ADD|SUB|AND|OR) +r\\d+, +r\\d+, +r\\d+ +<< +\\d+ *")) {
			// ADD/SUB/AND/OR rd, rs1, rs2 << #s_imm5
			
			int rd, rs1, rs2, imm5;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			matcher.find();
			imm5 = Integer.parseInt(matcher.group());
			
			if (imm5 > 16 || imm5 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			// ADD: 08H; SUB: 04H; AND: 00H; OR: 18H
			int op = asm.startsWith("ADD") ? 0x08 :
					asm.startsWith("SUB") ? 0x04 : 
					asm.startsWith("OR") ? 0x18 : 0x00;
			
			code = (op << 24) | (rs1 << 19) | (rd << 14) | (imm5 << 9) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println((asm.startsWith("ADD") ? "ADD " :
					asm.startsWith("SUB") ? "SUB " :
					asm.startsWith("AND") ? "AND " : "OR ")
					+"r"+rd+", r"+rs1+", r"+rs2+" << "+imm5);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("MOV +r\\d+, +r\\d+ *")) {
			// MOV rd, rs2
			
			int rd, rs2;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			
			int op = 0x1a;
			code = (op << 24) | (rd << 14) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("MOV r"+rd+", r"+rs2);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("MOV +r\\d+, +r\\d+ +<< +\\d+ *")) {
			// MOV rd, rs2 << #s_imm5
			
			int rd, rs2, imm5;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			matcher.find();
			imm5 = Integer.parseInt(matcher.group());

			if (imm5 > 16 || imm5 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			int op = 0x1a;
			code = (op << 24) | (rd << 14) | (imm5 << 9) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("MOV r"+rd+", r"+rs2+" << "+imm5);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("(LDB|LDW|STB|STW) +r\\d+, +\\[r\\d+\\+\\], +r\\d+ *") ||
				asm.matches("(LDB|LDW|STB|STW) +r\\d+, +\\[r\\d+\\-\\], +r\\d+ *")) {
			// LDB/LDW/STB/STW rd, [rs1+], rs2
			// LDB/LDW/STB/STW rd, [rs1-], rs2
			
			int rd, rs1, rs2;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			
			int op;
			if (asm.startsWith("LDB")){
				if (asm.contains("+"))
					op = 0x5d;
				else op = 0x55;
			}else if (asm.startsWith("LDW")){
				if (asm.contains("+"))
					op = 0x59;
				else op = 0x51;
			}else if (asm.startsWith("STB")){
				if (asm.contains("+"))
					op = 0x5c;
				else op = 0x54;
			}else{
				if (asm.contains("+"))
					op = 0x58;
				else op = 0x50;
			}
			
			code = (op << 24) | (rs1 << 19) | (rd << 14) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println((asm.startsWith("LDB") ? "LDB " :
					asm.startsWith("LDW") ? "LDW " :
					asm.startsWith("STB") ? "STB " : "STW ")
					+"r"+rd+", [r"+rs1+"(+|-)], r"+rs2);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("(LDB|LDW|STB|STW) +r\\d+, +\\[r\\d+\\+\\], +r\\d+ +<< +\\d+ *") ||
				asm.matches("(LDB|LDW|STB|STW) +r\\d+, +\\[r\\d+\\-\\], +r\\d+ +<< +\\d+ *") ) {
			// LDB/LDW/STB/STW rd, [rs1+], rs2 << #s_imm5
			// LDB/LDW/STB/STW rd, [rs1-], rs2 << #s_imm5
			
			int rd, rs1, rs2, imm5;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			matcher.find();
			imm5 = Integer.parseInt(matcher.group());
			
			if (imm5 > 16 || imm5 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			int op;
			if (asm.startsWith("LDB")){
				if (asm.contains("+"))
					op = 0x5d;
				else op = 0x55;
			}else if (asm.startsWith("LDW")){
				if (asm.contains("+"))
					op = 0x59;
				else op = 0x51;
			}else if (asm.startsWith("STB")){
				if (asm.contains("+"))
					op = 0x5c;
				else op = 0x54;
			}else{
				if (asm.contains("+"))
					op = 0x58;
				else op = 0x50;
			}
			
			code = (op << 24) | (rs1 << 19) | (rd << 14) | (imm5 << 9) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println((asm.startsWith("LDB") ? "LDB " :
					asm.startsWith("LDW") ? "LDW " :
					asm.startsWith("STB") ? "STB " : "STW ")
					+"r"+rd+", [r"+rs1+"+], r"+rs2+" << "+imm5);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("CMPSUB.A +r\\d+, +r\\d+ *")) {
			// CMPSUB.A rs1, rs2
			
			int rs1, rs2;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			
			int op = 0x15;
			code = (op << 24) | (rs1 << 19) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("CMPSUB.A r"+rs1+", r"+rs2);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("CMPSUB\\.A +r\\d+, +r\\d+ +<< +\\d+ *")) {
			// CMPSUB.A rs1, rs2 << #s_imm5
			
			int rs1, rs2, imm5;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			matcher.find();
			imm5 = Integer.parseInt(matcher.group());

			if (imm5 > 16 || imm5 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			int op = 0x15;
			code = (op << 24) | (rs1 << 19) | (imm5 << 9) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("CMPSUB.A r"+rs1+", r"+rs2+" << "+imm5);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("JUMP +r\\d+ *")) {
			// JUMP rs2
			
			int rs2;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			
			int op = 0x10;
			int func = 0x09;
			int rs1 = 0x1f;
			int rd = 0x1f;
			code = (op << 24) | (rs1 << 19) | (rd << 14) | (func << 5) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("JUMP r"+rs2);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("JUMP\\.L +r\\d+ *")) {
			// JUMP.L rs2
			
			int rs2;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			
			int op = 0x11;
			int func = 0x09;
			int rs1 = 0x1f;
			int rd = 0x1f;
			code = (op << 24) | (rs1 << 19) | (rd << 14) | (func << 5) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("JUMP.L r"+rs2);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("(ADD|SUB|AND|OR) +r\\d+, +r\\d+, +\\d+ *")) {
			// ADD/SUB/AND/OR rd, rs1, imm9
			
			int rd, rs1, imm9;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			imm9 = Integer.parseInt(matcher.group());
			
			if (imm9 > 256 || imm9 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			int op = asm.startsWith("ADD") ? 0x28 :
				asm.startsWith("SUB") ? 0x24 :
				asm.startsWith("AND") ? 0x20 : 0x38;
			code = (op << 24) | (rs1 << 19) | (rd << 14) | imm9;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println((asm.startsWith("ADD") ? "ADD " :
						asm.startsWith("SUB") ? "SUB " :
						asm.startsWith("AND") ? "AND " : "OR ")
						+"r"+rd+", r"+rs1+", "+imm9);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("(ADD|SUB|AND|OR) +r\\d+, +r\\d+, +\\d+ +<> +\\d+ *")) {
			// ADD/SUB/AND/OR rd, rs1, imm9 <> imm5
			
			int rd, rs1, imm9, imm5;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			imm9 = Integer.parseInt(matcher.group());
			matcher.find();
			imm5 = Integer.parseInt(matcher.group());

			if (imm9 > 256 || imm9 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			if (imm5 > 16 || imm5 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			int op = asm.startsWith("ADD") ? 0x28 :
				asm.startsWith("SUB") ? 0x24 :
				asm.startsWith("AND") ? 0x20 : 0x38;
			code = (op << 24) | (rs1 << 19) | (rd << 14) | (imm5 << 9) | imm9;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println((asm.startsWith("ADD") ? "ADD " :
						asm.startsWith("SUB") ? "SUB " :
						asm.startsWith("AND") ? "AND " : "OR ")
						+"r"+rd+", r"+rs1+", "+imm9+" <> "+imm5);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("MOV +r\\d+, +\\d+ *")) {
			// MOV rd, imm9
			
			int rd, imm9;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			imm9 = Integer.parseInt(matcher.group());

			if (imm9 > 256 || imm9 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			int op = 0x3a;
			code = (op << 24) | (rd << 14) | imm9;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("MOV r"+rd+", "+imm9);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("MOV +r\\d+, +\\d+ +<> +\\d+ *")) {
			// MOV rd, imm9 <> imm5
			
			int rd, imm9, imm5;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			imm9 = Integer.parseInt(matcher.group());
			matcher.find();
			imm5 = Integer.parseInt(matcher.group());

			if (imm9 > 256 || imm9 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			if (imm5 > 16 || imm5 < 0) {
				err("Immediate value out of range: "+asm);
				return 0;
			}
			
			int op = 0x3a;
			code = (op << 24) | (rd << 14) | (imm5 << 9) | imm9;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("MOV r"+rd+", "+imm9+" <> "+imm5);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("MULSL +r\\d, +r\\d+, +r\\d+, +r\\d+ *")) {
			// MULSL rd1, rd2, rs1, rs2
			
			int rd1, rd2, rs1, rs2;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd1 = Integer.parseInt(matcher.group());
			matcher.find();
			rd2 = Integer.parseInt(matcher.group());
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			matcher.find();
			rs2 = Integer.parseInt(matcher.group());
			
			int op = 0x08;
			int func = 0x09;
			code = (op << 24) | (rs1 << 19) | (rd1 << 14) | (rd2 << 9) | (func << 5) | rs2;
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("MULSL r"+rd1+", r"+rd2+", r"+rs1+", r"+rs2);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("B +(|-)\\d+ *")) {
			// B #imm24
			
			int imm24;
			matcher = immPattern.matcher(asm);
			matcher.find();
			imm24 = Integer.parseInt(matcher.group());
			
			if (imm24 > 8388607 || imm24 < -8388608) {
				err("Immediate value out of range: "+asm);
				return 0;				
			}
			
			int op = 0xbc;
			code = (op << 24) | (imm24 & 0xffffff);
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("B "+imm24);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("B\\.L +(|-)\\d+ *")) {
			// B.L #imm24
			
			int imm24;
			matcher = immPattern.matcher(asm);
			matcher.find();
			imm24 = Integer.parseInt(matcher.group());

			if (imm24 > 8388607 || imm24 < -8388608) {
				err("Immediate value out of range: "+asm);
				return 0;				
			}
			
			int op = 0xbd;
			code = (op << 24) | (imm24 & 0xffffff);
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println("B.L "+imm24);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("(BFZ|BEQ|BNZ|BNE|BFC|BEA|BNC|BUB|BFS|BNS" +
				"|BFV|BNV|BUA|BEB|BEG|BSL|BSG|BEL) +(|-)\\d+ *")) {
			// Bcc #imm24
			
			int imm24;
			matcher = immPattern.matcher(asm);
			matcher.find();
			imm24 = Integer.parseInt(matcher.group());

			if (imm24 > 8388607 || imm24 < -8388608) {
				err("Immediate value out of range: "+asm);
				return 0;				
			}
			
			int op = (asm.startsWith("BFZ") || asm.startsWith("BEQ")) ? 0xa0 :
				(asm.startsWith("BNZ") || asm.startsWith("BNE")) ? 0xa2 :
				(asm.startsWith("BFC") || asm.startsWith("BEA")) ? 0xa4 :
				(asm.startsWith("BNC") || asm.startsWith("BUB")) ? 0xa6 :
				asm.startsWith("BFS") ? 0xa8 :
				asm.startsWith("BNS") ? 0xaa :
				asm.startsWith("BFV") ? 0xac :
				asm.startsWith("BNV") ? 0xae :
				asm.startsWith("BUA") ? 0xb0 :
				asm.startsWith("BEB") ? 0xb2 :
				asm.startsWith("BEG") ? 0xb4 :
				asm.startsWith("BSL") ? 0xb6 :
				asm.startsWith("BSG") ? 0xb8 : 0xba;
			code = (op << 24) | (imm24 & 0xffffff);
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println(asm.substring(0, 3)
						+" "+imm24);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("(BFZ|BEQ|BNZ|BNE|BFC|BEA|BNC|BUB|BFS|BNS" +
				"|BFV|BNV|BUA|BEB|BEG|BSL|BSG|BEL)\\.L +(|-)\\d+ *")) {
			// Bcc.L #imm24
			
			int imm24;
			matcher = immPattern.matcher(asm);
			matcher.find();
			imm24 = Integer.parseInt(matcher.group());

			if (imm24 > 8388607 || imm24 < -8388608) {
				err("Immediate value out of range: "+asm);
				return 0;				
			}
			
			int op = (asm.startsWith("BFZ") || asm.startsWith("BEQ")) ? 0xa1 :
				(asm.startsWith("BNZ") || asm.startsWith("BNE")) ? 0xa3 :
				(asm.startsWith("BFC") || asm.startsWith("BEA")) ? 0xa5 :
				(asm.startsWith("BNC") || asm.startsWith("BUB")) ? 0xa7 :
				asm.startsWith("BFS") ? 0xa9 :
				asm.startsWith("BNS") ? 0xab :
				asm.startsWith("BFV") ? 0xad :
				asm.startsWith("BNV") ? 0xaf :
				asm.startsWith("BUA") ? 0xb1 :
				asm.startsWith("BEB") ? 0xb3 :
				asm.startsWith("BEG") ? 0xb5 :
				asm.startsWith("BSL") ? 0xb7 :
				asm.startsWith("BSG") ? 0xb9 : 0xbb;
			code = (op << 24) | (imm24 & 0xffffff);
			
			if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_INFO) {
				System.out.println(asm.substring(0, 3)
						+".L "+imm24);
				System.out.println(code);
			}
			
			return code;
		}
		
		if (asm.matches("(LDB|LDW|STB|STW) +r\\d+, +\\[r\\d+\\+\\], +\\d+ *") ||
				asm.matches("(LDB|LDW|STB|STW) +r\\d+, +\\[r\\d+\\-\\], +\\d+ *") ||
				asm.matches("(LDB|LDW|STB|STW) +r\\d+, +\\[r\\d+\\] *")				
				) {
			// LDB/LDW/STB/STW rd, [rs1+], #imm14
			// LDB/LDW/STW/STW rd, [rs1]
		
			int rd, rs1, imm14;
			matcher = digitPattern.matcher(asm);
			matcher.find();
			rd = Integer.parseInt(matcher.group());
			matcher.find();
			rs1 = Integer.parseInt(matcher.group());
			if (asm.contains("+") || asm.contains("-")){
				matcher.find();
				imm14 = Integer.parseInt(matcher.group());
			}else{
				imm14 = 0;
			}
			
			int op;
			if (asm.startsWith("LDB")){
				if (asm.contains("-"))
					op = 0x75;
				else
					op = 0x7D;
					
			}else if (asm.startsWith("LDW")){
				if (asm.contains("-"))
					op = 0x71;					
				else 
					op = 0x79;
				
			}else if (asm.startsWith("STB")){
				if (asm.contains("-"))
					op = 0x74;
				else
					op = 0x7c;
			}else{
				if (asm.contains("-"))
					op = 0x70;					
				else
					op = 0x78;				
			}			
			
			code = (op << 24) | (rs1 << 19) | (rd << 14) | imm14;						
			
			
			return code;
		}
		
		err("Assembly code not accepted: "+asm);
		return code;
	}
	
	private static void err(String error) {

		if (Mode.getDebugLevel() >= Mode.DEBUG_LEVEL_PRINT_ERR) {
			System.err.println(error);
		}
		GUIOutput.outputError(error);
		CentralProcessorUnit.getInstance().makeStop();
	}
}
